package frontend.pages.worklog.daily;

import backend.model.worklog.WorkLog;
import frontend.pages.reports.commuter.CommutersReportTableTemplate;
import shared.util.CalendarUtils;
import org.apache.wicket.Localizer;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import java.io.Serializable;
import java.util.*;

public class DefaultWorkLogTableTemplate implements Serializable {

    private static final String RESOURCE_KEY_TABLE_HEADER_DATE = "table.header.date";
    private static final String RESOURCE_KEY_TABLE_HEADER_EMPLOYEE = "table.header.employee";
    private static final String RESOURCE_KEY_TABLE_HEADER_OCCUPATION = "table.header.occupation";
    private static final String RESOURCE_KEY_TABLE_HEADER_TEAM = "table.header.team";
    private static final String RESOURCE_KEY_TABLE_HEADER_FOREMAN = "table.header.foreman";
    private static final String RESOURCE_KEY_TABLE_HEADER_PROJECT = "table.header.project";
    private static final String RESOURCE_KEY_TABLE_HEADER_SFI = "table.header.sfi";
    private static final String RESOURCE_KEY_TABLE_HEADER_ACTIVITY = "table.header.activity";
    private static final String RESOURCE_KEY_TABLE_HEADER_DEPARTMENT = "table.header.department";
    private static final String RESOURCE_KEY_TABLE_HEADER_WORKPLACE = "table.header.workplace";
    private static final String RESOURCE_KEY_TABLE_HEADER_WORK_DETAILS = "table.header.workDetails";
    private static final String RESOURCE_KEY_TABLE_HEADER_SHIFT = "table.header.shift";
    private static final String RESOURCE_KEY_TABLE_HEADER_NORMAL_HOURS = "table.header.hours";

    protected List<IColumn<WorkLog>> columns = new LinkedList<IColumn<WorkLog>>();
    protected List<String> header = new LinkedList<String>();

    public static Map<String, Comparator<WorkLog>> comparatorMap = new HashMap<String, Comparator<WorkLog>>()
        {{
            put("team", getByTeamComparator());
            put("employee", getByEmployeeComparator());
            put("employee", getByIdentificationCardComparator());
            put("occupation", getByOccupationComparator());
            put("foreman", getByForemanComparator());
            put("date", getByDateComparator());
            put("sfi", getBySfiComparator());
            put("activity", getByActivityComparator());
            put("department", getByDepartmentComparator());
            put("project", getByProjectComparator());
            put("workplace", getByWorkplaceComparator());
            put("workDetail", getByWorkDetailsComparator());
            put("shift", getByShiftComparator());
            put("hours", getByHoursComparator());
        }};

    public DefaultWorkLogTableTemplate() {
        createColumns();
    }

    public List<IColumn<WorkLog>> getColumns() {
        return columns;
    }

    public List<String> getHeader() {
        return header;
    }

    protected void createColumns() {
        createDefaultColumns();
    }

    private void createDefaultColumns() {
        columns.add(getIdentificationCardColumn());
        columns.add(getOccupationColumn());
        columns.add(getTeamColumn());
        columns.add(getForemanColumn());
        columns.add(getProjectColumn());
        columns.add(getSfiColumn());
        columns.add(getActivityColumn());
        columns.add(getDepartmentColumn());
        columns.add(getWorkPlaceColumn());
        columns.add(getWorkDetailsColumn());
        columns.add(getShiftColumn());
        columns.add(getHoursColumn());
    }

    protected AbstractColumn<WorkLog> getEmployeeColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_EMPLOYEE, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "employee", "employee");
    }

    protected AbstractColumn<WorkLog> getIdentificationCardColumn() {
        String columnName = Localizer.get().getString(CommutersReportTableTemplate.RESOURCE_KEY_TABLE_HEADER_IDENTIFICATION_CARD, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "identificationCard", "identificationCard");
    }

    protected AbstractColumn<WorkLog> getOccupationColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_OCCUPATION, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "occupation", "occupation");
    }

    protected AbstractColumn<WorkLog> getTeamColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_TEAM, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "team", "team");
    }

    protected AbstractColumn<WorkLog> getForemanColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_FOREMAN, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "foreman", "foreman");
    }

    protected AbstractColumn<WorkLog> getDateColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_DATE, null);
        header.add(columnName);
        return new AbstractColumn<WorkLog>(new Model<String>(columnName), "date") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLog>> cellItem, String componentId, IModel<WorkLog> rowModel) {
                WorkLog workLog = rowModel.getObject();
                cellItem.add(new Label(componentId, CalendarUtils.formatDate(workLog.getDate())));
            }
        };
    }

    protected AbstractColumn<WorkLog> getSfiColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_SFI, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "sfi", "sfi");
    }

    protected AbstractColumn<WorkLog> getActivityColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_ACTIVITY, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "activity", "activity");
    }

    protected AbstractColumn<WorkLog> getDepartmentColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_DEPARTMENT, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "department", "department");
    }

    protected AbstractColumn<WorkLog> getProjectColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_PROJECT, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "project", "project");
    }

    protected AbstractColumn<WorkLog> getWorkPlaceColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_WORKPLACE, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "workplace", "workplace");
    }

    protected AbstractColumn<WorkLog> getWorkDetailsColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_WORK_DETAILS, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "workDetail", "workDetail");
    }

    protected AbstractColumn<WorkLog> getShiftColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_SHIFT, null);
        header.add(columnName);
        return new PropertyColumn<WorkLog>(new Model<String>(columnName), "shift", "shift");
    }

    protected AbstractColumn<WorkLog> getHoursColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_NORMAL_HOURS, null);
        header.add(columnName);
        return new AbstractColumn<WorkLog>(new Model<String>(columnName), "normalHours") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLog>> cellItem, String componentId, IModel<WorkLog> rowModel) {
                WorkLog workLog = rowModel.getObject();
                int normalHours = workLog.getHours();
                cellItem.add(new Label(componentId, normalHours > 0 ? String.valueOf(normalHours) : ""));
            }
        };
    }

    protected void removeColumn(int index) {
        columns.remove(index);
        header.remove(index);
    }

    protected static Comparator<WorkLog> getByDateComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getDate().compareTo(workLog2.getDate());
            }
        };
    }

    protected static Comparator<WorkLog> getByEmployeeComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getEmployee().compareTo(workLog2.getEmployee());
            }
        };
    }

    protected static Comparator<WorkLog> getByIdentificationCardComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getEmployee().getIdentificationCard().compareTo(workLog2.getEmployee().getIdentificationCard());
            }
        };
    }

    protected static Comparator<WorkLog> getByOccupationComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getOccupation().compareTo(workLog2.getOccupation());
            }
        };
    }

    protected static Comparator<WorkLog> getByTeamComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getTeam().compareTo(workLog2.getTeam());
            }
        };
    }

    protected static Comparator<WorkLog> getByForemanComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return workLog1.getForeman().compareTo(workLog2.getForeman());
            }
        };
    }

    protected static Comparator<WorkLog> getBySfiComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getSfi() == null) {
                    return -1;
                }
                return workLog1.getSfi().compareTo(workLog2.getSfi());
            }
        };
    }

    protected static Comparator<WorkLog> getByActivityComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getSfi() == null || workLog1.getSfi().getActivity() == null) {
                    return -1;
                }
                return workLog1.getSfi().getActivity().compareTo(workLog2.getSfi().getActivity());
            }
        };
    }

    protected static Comparator<WorkLog> getByDepartmentComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getSfi() == null || workLog1.getSfi().getDepartment() == null) {
                    return -1;
                }
                return workLog1.getSfi().getDepartment().compareTo(workLog2.getSfi().getDepartment());
            }
        };
    }

    protected static Comparator<WorkLog> getByProjectComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getProject() == null) {
                    return -1;
                }
                return workLog1.getProject().compareTo(workLog2.getProject());
            }
        };
    }

    protected static Comparator<WorkLog> getByWorkDetailsComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getWorkDetail() == null) {
                    return -1;
                }
                return workLog1.getWorkDetail().compareTo(workLog2.getWorkDetail());
            }
        };
    }

    protected static Comparator<WorkLog> getByWorkplaceComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getWorkplace() == null) {
                    return -1;
                }
                return workLog1.getWorkplace().compareTo(workLog2.getWorkplace());
            }
        };
    }

    protected static Comparator<WorkLog> getByShiftComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                if (workLog1.getShift() == null) {
                    return -1;
                }
                return workLog1.getShift().compareTo(workLog2.getShift());
            }
        };
    }

    protected static Comparator<WorkLog> getByHoursComparator() {
        return new Comparator<WorkLog>() {
            @Override
            public int compare(WorkLog workLog1, WorkLog workLog2) {
                return Integer.valueOf(workLog1.getHours()).compareTo(workLog2.getHours());
            }
        };
    }
}
